#ifndef __HELPERS_HPP__
#define __HELPERS_HPP__

#include "region.hpp"
#include "village.hpp"

struct Edge;
struct EdgeHash;
struct EdgeEqual;
struct Node;
struct NodeHash;
struct NodeEqual;
struct Graph;

struct Node
{
    int value; // _id
    int in;
    int out;
    std::vector<Node *> nexts; // 当前节点为from，to的节点的集合
    std::vector<Edge *> edges;

    Node(int value)
    {
        this->value = value;
        in = 0;
        out = 0;
    }
    Node() = default;
};

struct NodeHash
{
    size_t operator()(const Node &k) const
    {
        return k.value;
    }
};

struct NodeEqual
{
    bool operator()(const Node &lhs, const Node &rhs) const
    {
        return lhs.value == rhs.value;
    }
};

struct Edge
{
    double weight;
    Node *from;
    Node *to;

    Edge(double weight, Node *from, Node *to)
    {
        this->weight = weight;
        this->from = from;
        this->to = to;
    }
};

struct EdgeHash
{
    size_t operator()(const Edge &k) const
    {
        std::stringstream ostr;
        ostr << k.from->value << "," << k.to->value;

        std::hash<std::string> h;
        size_t n = h(ostr.str());

        return n;
    }
};

struct EdgeEqual
{
    bool operator()(const Edge &lhs, const Edge &rhs) const
    {
        return (lhs.from->value == rhs.from->value) && (lhs.to->value == rhs.to->value);
    }
};

struct Graph
{
    unordered_map<int, Node *> nodes;
    unordered_set<Edge *> edges;
};

MatrixXd region_to_mat(Region region);
Graph matrix_to_graph(MatrixXd m);
Graph unordered_set_to_graph(unordered_set<Edge, EdgeHash, EdgeEqual> uset);
MatrixXd unordered_set_to_matrix(unordered_set<Edge, EdgeHash, EdgeEqual> uset);

// unordered_set<Edge, EdgeHash, EdgeEqual> kruskalMST(Graph graph);
unordered_set<Edge, EdgeHash, EdgeEqual> primMST(Graph graph);

std::vector<Node> shortest_path(Graph graph, Node from, Node to);

#endif /* __HELPERS_HPP__ */